﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using NVelocity.App;
using Commons.Collections;
using System.Collections;
using System.IO;
using NVelocity;
using System.Collections.Specialized;

namespace ExtEasy.Base
{   
    /// <summary>
    /// Результат запроса 
    /// </summary>
    [Serializable]
    public class ExtAjaxRes
    {
        private string _html = "";
        public string HTML
        {
            get { return _html; }
            set { _html = value; }// HttpUtility.HtmlEncode(value); }
        }
        public bool HasErrors = false;
        public string ErrorMessage;
        public string ID = "";
        public string BackScript = "";
    }


    /// <summary>
    /// Базовый класс для контролов
    /// </summary>
    public abstract class ExtControl: IDisposable
    {
        #region Constructors

        public ExtControl()
        {
            ID = this.GetType().Assembly.GetName().Name;
        }

        public ExtControl(string id)
        {
            Init(id);            
        }        

        public virtual void Init(string id)
        {            
            ID = id;
            StartTag = string.Format("<div id=\"{0}\" class=\"\" style=\"\" title=\"\">",id);
            EndTag = "</div>";
            HTMLChanged = true;
            //_template = ExtRoot<ExtModel>.Templates.GetTemplate(this.GetType().Name);
        }

        #endregion



        #region Members

        public string ID { get; set; }
        protected DateTime _date;
        private string _HTML;
        protected string _ChangeScript;
        public string ChangeScript
        {
            get { return _ChangeScript; }
            set { HTMLChanged = true; _ChangeScript = value; }
        }
        protected bool HTMLChanged = true;
        protected string StartTag = "";
        protected string EndTag = "";
        protected bool _readOnly = false;
        protected string _template = "";

        private bool _isvisible = true;
        public bool IsVisible { get { return _isvisible; } set { _isvisible = value; HTMLChanged = true; } }
        
        public string CtrlKey { get; set; }
        //public string ControlKey
        //{
        //    get { return _ControlKey; }
        //}

        public ExtModel Parent { get; set; }
        //public ExtModel Parent
        //{
        //    get { return _Parent; }
        //}
        

        #endregion



        #region Properties
        
        public DateTime Date
        {
            get { return _date; }
        }

        /// <summary>
        /// Внутренний HTML (рендерит сам если нужно)
        /// </summary>
        public string HTML
        {
            get { if (HTMLChanged) { Render(); } return _HTML; }
        }

        /// <summary>
        /// Весь HTML с открывающим и закрывающим тэгами (рендерит сам если нужно)        
        /// </summary>
        public string FullHTML
        {
            get { return HTMLChanged ? Render() : StartTag + _HTML + EndTag; }
        }

        public bool ReadOnly
        {
            get { return _readOnly; }
        }


        public string AbsolutePath
        {
            get { return ExtUtils.GetAbsolutePath(); }
        }

        public string GetAbsolutePath(string s)
        {
            return ExtUtils.GetAbsolutePath() + s;
        }
        #endregion



        #region Methods
        public virtual void Dispose()
        {
            // Уничтожние модели
        }

        public void RefreshDate()
        {
            _date = DateTime.Now;
        }


        public string ConcatString(params string[] p)
        {
            string res = "";
            for (int i = 0; i < p.Length; i++)
            {
                res += p[i];
            }
            return res;
        }

        /// <summary>
        /// Метод для наследников - надо перегрузить
        /// </summary>
        /// <returns></returns>
        protected virtual string RenderControl()
        {
            return RenderControl(this.GetType().Name);
        }

        /// <summary>
        /// Метод для наследников - надо перегрузить
        /// </summary>
        /// <returns></returns>
        protected virtual string RenderControl(string templatename)
        {
            //throw new Exception("Должен быть перегружен!");
           /// return StartTag + EndTag;
           /// 
            if (!_isvisible) return string.Empty;

            StringWriter stringWriter = new StringWriter();

            try
            {

                VelocityEngine Engine = new VelocityEngine();
                ExtendedProperties props = new ExtendedProperties();
                props.SetProperty("resource.loader", "assembly");
                props.SetProperty("assembly.resource.loader.class", "NVelocity.Runtime.Resource.Loader.AssemblyResourceLoader,NVelocity");
                props.SetProperty("assembly.resource.loader.assembly", this.GetType().Assembly.GetName().Name/*"ExtEasy"*/);
                Engine.Init(props);

                Hashtable context = new Hashtable();
                context.Add("this", this);                

                VelocityContext velocityContext = new VelocityContext(context);
                Engine.MergeTemplate(this.GetType().Assembly.GetName().Name + ".Templates." + /*this.GetType().Name*/templatename + ".tmpl", Encoding.UTF8.WebName, velocityContext, stringWriter);

               

                //NVelocity.Template t = new Template();
                //t.Data = "";
                //t.Merge(velocityContext, stringWriter);
            }
            catch (Exception ex)
            {
                stringWriter.Write(string.Format("Ошибка рендеринга {0} сборки {1}: {2}", this.GetType().Name, this.GetType().Assembly.GetName().Name,ex.Message));
            }

            return stringWriter.ToString();

        }

        /// <summary>
        /// Метод обработки аякс=запросов к контролу. Нужно пегрузить.
        /// </summary>
        /// <param name="c">Параметры вызова</param>
        /// <returns></returns>
        public abstract ExtAjaxRes ProcessOperation(NameValueCollection c);
       

        public string GetRnd()
        {
            return ExtUtils.GetMD5Hash(DateTime.Now.ToLongTimeString());
        }

        /// <summary>
        /// Принудительно отрендерить контрол
        /// </summary>
        /// <returns></returns>
        public string Render()
        {
            HTMLChanged = false;
            _HTML = RenderControl();
            return StartTag + _HTML + EndTag;
        }

        public string RenderByTemplate(string templatename)
        {
            return RenderControl(templatename);
        }
                
        #endregion        
    }
}
